/*
    created: 2023/4/5
    filename: Singleton.h
    author: 李东霖
    purpose: 单例模式的演示代码

*/

#ifndef _SINGLETON_H_
#define _SINGLETON_H_

#include<mutex>
#include<iostream>
//测试单例
class Singleton 
{ 
public: 
 Singleton(){}; 
 ~Singleton(){}; 
 // 静态成员函数,提供全局访问的接口
 static Singleton* GetInstancePtr(); 
 static Singleton GetInstance(); 
 void Test(); 
private: 
 // 静态成员变量,提供全局惟一的一个实例
 static Singleton* m_pStatic; 
};

/*
//我们抽象一个类模板
//c++11标准

template <class T>
class Singleton
{
public:
    //提供一个静态的全局访问接口
    static T* GetInstance();
protected:

    Singleton();
    virtual ~Singleton() = default;

private:
    //指向他的唯一实现，需要在类外赋值
    //他是线程安全的
    // static Singleton* m_pSingle;
    //不允许拷贝和移动
    Singleton(const T&) = delete;
    void operator=(const T&) = delete;
    //定义了拷贝编译器是不会生成移动的，但是我还是写出来
    Singleton(T&&) = delete;
    void operator=(T&&) = delete;
};

/*
//两种实现方式
//懒汉式，比较传统的实现方法  考虑线程安全  
//就是在需要这个对象的时候才开始创建  

template <class T,bool is_thread_safe = true>
class LazySingleton
{
public:
    //提供一个静态的全局访问接口
    static T* GetInstance();
protected:

    LazySingleton() = default;
    //这里回收该指针，如果是智能指针则不需要操作
    virtual ~LazySingleton();

private:
    //指向他的唯一实现，需要在类外赋值
    //他需要保证线程安全 可以使用智能指针
    static LazySingleton* t_;
    //一个互斥量
    static std::mutex mtx_;
    //不允许拷贝和移动
    LazySingleton(const LazySingleton&) = delete;
    LazySingleton& operator=(const LazySingleton&) = delete;
    //定义了拷贝编译器是不会生成移动的，但是我还是写出来
    LazySingleton(LazySingleton&&) = delete;
    LazySingleton& operator=(LazySingleton&&) = delete;
};

//在类外我们需要初始化成员

template <class T,bool is_thread_safe >
LazySingleton<T,is_thread_safe>* LazySingleton<T,is_thread_safe>::t_;
    
//一个互斥量
template <class T,bool is_thread_safe >
std::mutex LazySingleton<T,is_thread_safe>::mtx_;



//饿汉式 
//这个没有线程安全问题，因为他在进入main函数之前就已经完成了初始化 
template<class T>
class EagerSingleton
{
public:
    static T& GetInstance()
    {
        return *t_;
    }

private:
    EagerSingleton(T&&) = delete;
    EagerSingleton(const T&) = delete;
    void operator= (const T&) = delete;

protected:
    EagerSingleton() = default;
    virtual ~EagerSingleton() = default;

private:
    static T* t_;

};

template<typename T>
T* EagerSingleton<T>::t_ = new (std::nothrow) T;
*/
#endif //!_SINGLETON_H_